﻿#pragma once

#include <cstdint>
#include <ctime>
#include <functional>
#include <memory>

namespace kratos {
namespace service {

/**
 * 定时器回调函数, 第一个参数为用户启动定时器时传递的用户数据，第二个参数为调用回调时的时间戳(毫秒）
 */
using SchedulerCallback = std::function<bool(std::uint64_t, std::time_t ms)>;

/**
 * 定时器调度器
 */
class Scheduler {
public:
  virtual ~Scheduler() {}
  /**
   * 运行一个调度器，所有非协程类定时器会在这个方法内运行
   *
   * \param ms 当前时间戳，毫秒
   * \param max_count 本次处理的最大数量，处理的定时器回调不会超过这个值
   * \return 本次处理的实际数量
   */
  virtual auto do_schedule(std::time_t ms, std::size_t max_count)
      -> std::size_t = 0;
  /**
   * 开启一个单次定时器
   *
   * \param duration 超时时间
   * \param cb 事件回调
   * \param udata 用户数据, 会在事件回调传回给用户
   * \return 定时器ID，不同的Scheduler产生的ID不会重复
   */
  virtual auto schedule(std::time_t duration, SchedulerCallback cb,
                        std::uint64_t udata) -> std::uint64_t = 0;
  /**
   * 开启一个单次定时器，通过协程来运行定时器
   *
   * \param duration 超时时间
   * \param cb 事件回调
   * \param udata 用户数据, 会在事件回调传回给用户
   * \return 定时器ID，不同的Scheduler产生的ID不会重复
   */
  virtual auto schedule_co(std::time_t duration, SchedulerCallback cb,
                           std::uint64_t udata) -> std::uint64_t = 0;
  /**
   * 开启一个循环定时器
   *
   * \param duration 超时时间
   * \param cb 事件回调
   * \param udata 用户数据, 会在事件回调传回给用户
   * \return 定时器ID，不同的Scheduler产生的ID不会重复
   */
  virtual auto schedule_many(std::time_t duration, SchedulerCallback cb,
                             std::uint64_t udata) -> std::uint64_t = 0;
  /**
   * 开启一个循环定时器，通过协程来运行定时器
   *
   * \param duration 超时时间
   * \param cb 事件回调
   * \param udata 用户数据, 会在事件回调传回给用户
   * \return 定时器ID，不同的Scheduler产生的ID不会重复
   */
  virtual auto schedule_co_many(std::time_t duration, SchedulerCallback cb,
                                std::uint64_t udata) -> std::uint64_t = 0;
  /**
   * 取消一个定时器
   *
   * \param id 定时器ID
   * \return 成功或失败
   */
  virtual auto cancel(std::uint64_t id) -> bool = 0;

  /**
   * 取得定时器总数量，包含协程定时器和非协程定时器
   *
   * \return 定时器总数量
   */
  virtual auto size() -> std::size_t = 0;
  /**
   * 取得协程定时器总数量
   * 
   * \return 协程定时器总数量
   */
  virtual auto size_co() -> std::size_t = 0;
  /**
   * 取得非协程定时器总数量
   *
   * \return 非协程定时器总数量
   */
  virtual auto size_noco() -> std::size_t = 0;
};

} // namespace service
} // namespace kratos
